<?php
/**
 * $Id: app.php 27 2009-06-27 02:26:17Z eyou80 $
 */

/**
 * 应用类
 *
 * @package App
 */
class Tinyask_App
{
	/**
	 * 应用对象池
	 *
	 * @var array
	 */
	private static $_appPool = array();

	/**
	 * 帮手列表
	 *
	 * @var array
	 */
	private $_helpers = array();

	/**
	 * 数据堆栈
	 *
	 * @var array
	 */
	protected $stack = array();

	/**
	 * 单条数据
	 *
	 * @var array
	 */
	protected $row = array();

	/**
	 * 数据顺序, 从1开始
	 *
	 * @var integer
	 */
	public $index = 0;

	/**
	 * 队列长度
	 *
	 * @var integer
	 */
	public $length = 0;

	/**
	 * 执行函数
	 *
	 */
	public function execute()
	{}

	public function plugin($handle = null)
	{
		return Tinyask_Plugin::factory(empty($handle) ? get_class($this) : $handle);
	}

	/**
	 * 工厂方法,将类静态化放置到列表中
	 *
	 * @param string $alias 组建别名
	 * @param mixed $params 传递的参数
	 * @param mixed $request 前段参数
	 * @param boolean $enableResponse 是否允许http回执
	 * @throws Tinyask_App_Exception
	 * @return object
	 */
	public static function app($alias, $params = null, $request = null, $enableResponse = true)
	{
		list($className) = explode('@', $alias);

		if(!isset(self::$_appPool[$alias])) {
			$fileName = str_replace('_', '/', strtolower($className)) . '.php';
			require_once $fileName;

			if(!class_exists($className)) {
				require_once 'tinyask/app/exception.php';
				throw new Tinyask_App_Exception($className);
			}

			self::$_appPool[$alias] = new $className();

			if(!empty($params)) {
				self::$_appPool[$alias]->param->setDefault($params, true);
			}

			if(!empty($request)) {
				self::$_appPool[$alias]->request->flush($request);
			}

			if(!$enableResponse) {
				self::$_appPool[$alias]->response->disable();
			}

			self::$_appPool[$alias]->execute();
		}

		return self::$_appPool[$alias];
	}

	/**
	 * 释放组建
	 *
	 * @param string $alias
	 */
	public static function destory($alias)
	{
		if(isset(self::$_appPool[$alias])) {
			unset(self::$_appPool[$alias]);
		}
	}

	/**
	 * 将对象本身赋值
	 *
	 * @param string $var
	 */
	public function to(&$var)
	{
		$var = $this;
	}

	/**
	 * 格式化数据
	 *
	 * @param 数据格式 $format
	 */
	public function parse($format)
	{
		$rowsKey = array();

		foreach ($this->row as $key => $value) {
			if(is_array($value) || is_object($value)) {
				unset($this->row[$key]);
			} else {
				$rowsKey[] = '{' . $key . '}';
			}
		}

		foreach ($this->stack as $val) {
			foreach ($val as $key => $value) {
				if(is_array($value) || is_object($value)) {
					unset($val[$key]);
				}
			}
			echo str_replace($rowsKey, $val, $format) . "\n";
		}

		reset($this->row);
		reset($this->stack);
	}

	/**
	 * 将数据压入堆栈
	 *
	 * @param array $value
	 */
	public function push(array $value)
	{
		$this->row = $value;
		$this->length ++;
		$this->stack[] = $value;
	}

	/**
	 * 根据余数输出
	 *
	 */
	public function remainded()
	{
		$args = func_get_args();
		$num = func_num_args();
		$remainded = $this->index % $num;
		echo $args[($remainded == 0 ? $num : $remainded) -1];
	}

	/**
	 * 输出顺序值
	 *
	 */
	public function index()
	{
		echo $this->index;
	}

	/**
	 * 输出长度
	 *
	 */
	public function length()
	{
		echo $this->length;
	}

	/**
	 * 判断堆栈是否为空
	 *
	 * @return boolean
	 */
	public function isEmpty()
	{
		return empty($this->stack);
	}

	/**
	 * 返回堆栈中的当前行, 并把指针指向下一行
	 *
	 * @return mixed
	 */
	public function next()
	{
		if($this->stack) {
			$this->row = &$this->stack[key($this->stack)];
			next($this->stack);
			$this->index ++;
		}

		if(!$this->row) {
			reset($this->stack);
			$this->index = 0;
			return false;
		}

		return $this->row;
	}

	/**
	 * 魔术函数,用于挂接其它函数
	 *
	 * @param string $name
	 * @param array $args
	 */
	public function __call($name, $args)
	{
		echo $this->{$name};
	}

	/**
	 * 魔术函数,用于获取内部变量
	 *
	 * @param string $name
	 * @return mixed
	 */
	public function __get($name)
	{
		return isset($this->row[$name]) ? $this->row[$name] : (method_exists($this, $method = '__' . $name) ? $this->row[$name] = $this->{$method}() : (isset($this->_helpers[$name]) ? $this->_helpers[$name] : $this->__helper($name)));
	}

	/**
	 * 设定堆栈中的值
	 *
	 * @param string $name
	 * @param mixed $value
	 */
	public function __set($name, $value)
	{
		$this->row[$name] = $value;
	}

	/**
	 * 验证堆栈中的值是否存在
	 *
	 * @param string $name
	 * @return boolean
	 */
	public function __isset($name)
	{
		return isset($this->row[$name]);
	}

	/**
	 * 帮手
	 *
	 * @param string $name
	 * @return mixed
	 */
	public function __helper($name)
	{
		switch ($name) {
			case 'request':
				$this->_helpers[$name] = new Tinyask_App_Request();
				break;
			case 'response':
				$this->_helpers[$name] = new Tinyask_App_Response();
				break;
			case 'param':
				$this->_helpers[$name] = Tinyask_Config::factory();
				break;
			default:
				return null;
		}

		return $this->_helpers[$name];
	}
}
